#!/usr/bin/python

from importlib.machinery import SourceFileLoader

import sys
import ssl
import http.server

import PSConfig

import logging
logger = logging.getLogger(__name__)

# Parse params
gRequestHandlerName = PSConfig.REQUEST_HANDLER_NAME
gRequestHandlerFile = PSConfig.REQUEST_HANDLER_FILE
gHost = PSConfig.HOST
gPort = PSConfig.PORT
gCertFile = PSConfig.CERT_FILE
gKeyFile = PSConfig.KEY_FILE
gLogFile = PSConfig.LOG_FILE
gLogLevel = PSConfig.LOG_LEVEL
gServerInitializerName = PSConfig.SERVER_INITIALIZER_NAME
gServerInitializerFile = PSConfig.SERVER_INITIALIZER_FILE
paramOptions = {
    # True: string value
    # False: none string value
    "-RequestHandler": False,
    "-RequestHandlerName": True,
    "-RequestHandlerFile": True,
    "-Host": True,
    "-Port": False,
    "-CertFile": True,
    "-KeyFile": True,
    "-LogFile": True,
    "-LogLevel": False,
    "-ServerInitializer": False,
    "-ServerInitializerName": True,
    "-ServerInitializerFile": True
}
paramIndex = 1
paramLen = len(sys.argv)
while paramIndex < paramLen:
    option = sys.argv[paramIndex]
    if option not in paramOptions.keys():
        logger.error(f"Wrong option: {option}")
        exit(f"Wrong option: {option}")
    if paramIndex + 1 >= paramLen:
        logger.error(f"No param for option: {option}")
        exit(f"No param for option: {option}")
    # Overwrite configuration value by parameter value if there is
    value = f"\"{sys.argv[paramIndex + 1]}\"" if paramOptions[option] else sys.argv[paramIndex + 1]
    exec(option.replace("-", "g") + " = " + value)
    paramIndex += 2

# Load RequestHandler
handler = SourceFileLoader(gRequestHandlerName, gRequestHandlerFile).load_module()
exec(f"gRequestHandler = handler.{gRequestHandlerName}")

# Load ServerInitializer by parameter value
initializer = SourceFileLoader(gServerInitializerName, gServerInitializerFile).load_module()
exec(f"gServerInitializer = initializer.{gServerInitializerName}")

if __name__ == "__main__":
    logging.basicConfig(filename = gLogFile, level = gLogLevel)
    logger.debug("[Main] Start PServer")

    if not gServerInitializer().Initialize():
        logger.error("Initialize failed")
        exit("Initialize failed")

    serverClass = http.server.HTTPServer
    handlerClass = gRequestHandler
    serverAddress = (gHost, gPort)
    httpd = serverClass(serverAddress, handlerClass)

    # ssl.PROTOCOL_TLSv1_2 is deprecated
    context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
    context.load_cert_chain(gCertFile, gKeyFile)
    context.set_ciphers("@SECLEVEL=1:ALL")

    httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
    httpd.serve_forever();
